package com.xr.common.utils;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * 并行流工具类（提升批量插入大量数据（10w+ 甚至更高数据量）的性能）
 * <p>
 * 并行流 ：
 * <p>
 * 把一个内容分成多个数据块，并用不同的线程分 别处理每个数据块的流。
 * Java 8 中将并行进行了优化，我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流之间进行切换。
 */
public class ParallelStreamUtil {

    /**
     * 每个长SQL插入的行数，可以根据数据库性能调整
     */
    private final static int SIZE = 1000;

    /**
     * 如果需要调整并发数目，修改下面方法的第二个参数即可
     * 并行流使用的并发数是CPU的核心数，不能局部更改，全局更改影响较大（慎重使用）
     */
    static {
        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "8");
    }

    /**
     * 插入方法
     *
     * @param list     插入数据集合
     * @param consumer 消费型方法，直接使用 mapper::method 方法引用的方式
     * @param <T>      插入的数据类型
     */
    public static <T> boolean insertBatchOfLarge(List<T> list, Consumer<List<T>> consumer) {
        if (ObjectUtils.isEmpty(list) || list.size() == 0) {
            return false;
        }
        try {
            List<List<T>> streamList = new ArrayList<>();
            for (int i = 0; i < list.size(); i += SIZE) {
                int j = Math.min((i + SIZE), list.size());
                List<T> subList = list.subList(i, j);
                streamList.add(subList);
            }
            streamList.parallelStream().forEach(consumer);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

}
